#include "bsp.h"

#include "SW_I2C/sw_i2c.h"

 
/* 定义IO = 1和 0的代码  */
#define I2C_SDA_1()		AHT21_SDA_PORT->BSRR = AHT21_SDA_PIN
#define I2C_SDA_0()		AHT21_SDA_PORT->BSRR = AHT21_SDA_PIN << 16;

#define I2C_SCL_1()		AHT21_SCL_PORT->BSRR = AHT21_SCL_PIN
#define I2C_SCL_0()		AHT21_SCL_PORT->BSRR = AHT21_SCL_PIN << 16;

#define I2C_SDA_READ()  ((AHT21_SDA_PORT->IDR & AHT21_SDA_PIN) != 0)	/* 读SDA口线状态 */
#define I2C_SCL_READ()  ((AHT21_SCL_PORT->IDR & AHT21_SCL_PIN) != 0)	/* 读SCL口线状态 */

#define I2C_WR	0		/* 写控制bit */
#define I2C_RD	1		/* 读控制bit */

// I2C总线时序接口函数
static void I2C_SDA_LOW(void);
static void I2C_SDA_HIGH(void);
static void I2C_SCL_LOW(void);
static void I2C_SCL_HIGH(void);
static uint8_t I2C_SDA_READ_LEVEL(void);
static void I2C_SDA_SET_INPUT(void);
static void I2C_SDA_SET_OUTPUT(void);
static void I2C_Delay(uint32_t us);


/* Private variables ---------------------------------------------------------*/
// 定义i2c驱动对象
static sw_i2c_dev_t i2c_aht21_dev;

static void aht21_gpio_config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 打开GPIO时钟 */
    RCC_AHB1PeriphClockCmd(RCC_AHT21_PORT, ENABLE);

    /* 配置为开漏输出 */
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;		/* 设为输出口 */
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 	
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;


    GPIO_InitStructure.GPIO_Pin = AHT21_SDA_PIN;
    GPIO_Init(AHT21_SDA_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = AHT21_SCL_PIN;
    GPIO_Init(AHT21_SCL_PORT, &GPIO_InitStructure);

    /*释放SCL和SDA*/
    I2C_SDA_1();
    I2C_SCL_1();
}

static void aht21_i2c_config(void)
{
    i2c_aht21_dev.name               = "i2c_aht21";
    i2c_aht21_dev.speed              = 2; /*! speed:105Hz */
    i2c_aht21_dev.delay_us           = I2C_Delay;
    i2c_aht21_dev.ops.sda_low        = I2C_SDA_LOW;
    i2c_aht21_dev.ops.sda_high       = I2C_SDA_HIGH;
    i2c_aht21_dev.ops.scl_low        = I2C_SCL_LOW;
    i2c_aht21_dev.ops.scl_high       = I2C_SCL_HIGH;
    i2c_aht21_dev.ops.sda_read_level = I2C_SDA_READ_LEVEL;
    i2c_aht21_dev.ops.sda_set_input  = I2C_SDA_SET_INPUT;
    i2c_aht21_dev.ops.sda_set_output = I2C_SDA_SET_OUTPUT;
    sw_i2c_init(&i2c_aht21_dev); 
}

void bsp_aht21_init(void)
{
    uint8_t data_buf[3] = {0};
    sw_i2c_msg_t sw_i2c_msg;
    sw_i2c_msg.buf = data_buf;
    // 引脚初始化
    aht21_gpio_config();
    // 软件i2c初始化
    aht21_i2c_config();
    // 上电延时等待40ms
    HAL_Delay_ms(40);

    // 查看状态字的Bit[3]是否为1,否则进行初始化
    if((bsp_aht21_read_status() & 0x08) == 0)
    {
        sw_i2c_msg.addr = AHT21_I2C_ADDR;
        sw_i2c_msg.flags = SW_I2C_FLAG_WR;
        sw_i2c_msg.buf[0] = 0xBE;
        sw_i2c_msg.buf[1] = 0x08;
        sw_i2c_msg.buf[2] = 0x00;
        sw_i2c_msg.len = 3;
        sw_i2c_transfer(&i2c_aht21_dev, &sw_i2c_msg, 1); 
        HAL_Delay_ms(10); // 等待10ms
    }
}

// 读状态
uint8_t bsp_aht21_read_status(void)
{
    // 声明一个无符号8位变量，用于存储读取到的状态字节数据
    uint8_t Byte_first;	
    uint8_t data_buf[1] = {0};
    sw_i2c_msg_t sw_i2c_msg;
    sw_i2c_msg.buf = data_buf;
    sw_i2c_msg.addr = AHT21_I2C_ADDR;
    sw_i2c_msg.flags = SW_I2C_FLAG_RD;
    sw_i2c_msg.len = 1;
    sw_i2c_transfer(&i2c_aht21_dev, &sw_i2c_msg, 1); 
    Byte_first = sw_i2c_msg.buf[0]; // 读取状态字节数据

    return Byte_first;
}

// 软复位
void bsp_aht21_reset(void)
{
    uint8_t data_buf[1] = {0};
    sw_i2c_msg_t sw_i2c_msg;
    sw_i2c_msg.buf = data_buf;
    sw_i2c_msg.addr = AHT21_I2C_ADDR;
    sw_i2c_msg.flags = SW_I2C_FLAG_WR;
    sw_i2c_msg.buf[0] = 0xBA;
    sw_i2c_msg.len = 1;
    sw_i2c_transfer(&i2c_aht21_dev, &sw_i2c_msg, 1);
}

uint8_t bsp_aht21_read_data(float *humidity,float *temperature)
{
    uint8_t cnt = 5;
    uint32_t RetuData = 0; // 定义一个32位无符号整数，用于存储返回的数据

    uint8_t data_buf[6] = {0};
    sw_i2c_msg_t sw_i2c_msg;
    sw_i2c_msg.buf = data_buf;

    // 0xAC 触发测量
    sw_i2c_msg.addr = AHT21_I2C_ADDR;
    sw_i2c_msg.flags = SW_I2C_FLAG_WR;
    sw_i2c_msg.buf[0] = 0xAC;
    sw_i2c_msg.buf[1] = 0x33;
    sw_i2c_msg.buf[2] = 0x00;
    sw_i2c_msg.len = 3;
    sw_i2c_transfer(&i2c_aht21_dev, &sw_i2c_msg, 1);

    HAL_Delay_ms(80); // 等待测量完成

    while(bsp_aht21_read_status() & 0x80 && cnt) // 等待数据准备好
    {
        HAL_Delay_ms(5);
        cnt--;
    }
    if(cnt == 0)
    {
        return 1;
    }

    // 读取测量数据
    sw_i2c_msg.addr = AHT21_I2C_ADDR;
    sw_i2c_msg.flags = SW_I2C_FLAG_RD;
    sw_i2c_msg.len = 6;
    sw_i2c_transfer(&i2c_aht21_dev, &sw_i2c_msg, 1);
    // 0 状态字 1 湿度 2 湿度 3 湿度和温度(高湿度 低温度) 4 温度 5 温度 

    // 解析出湿度和温度数据
    RetuData = (RetuData|data_buf[1])<<8;
    RetuData = (RetuData|data_buf[2])<<8;
    RetuData = (RetuData|data_buf[3]);
    RetuData = RetuData >> 4;
    *humidity = (RetuData * 1000 >> 20);
    *humidity /= 10;

    RetuData = 0;
    RetuData = (RetuData|(data_buf[3]&0x0F))<<8;
    RetuData = (RetuData|data_buf[4])<<8;
    RetuData = (RetuData|data_buf[5]);
    RetuData = RetuData & 0xfffff;
    *temperature = ((RetuData * 2000 >> 20)- 500);
    *temperature /= 10;

	return 0;
}

/***********************************************************************/

static void I2C_SDA_LOW(void)
{
    I2C_SDA_0();
}

static void I2C_SDA_HIGH(void)
{
    I2C_SDA_1();
}

static void I2C_SCL_LOW(void)
{
    I2C_SCL_0();
}

static void I2C_SCL_HIGH(void)
{
    I2C_SCL_1();
}

static uint8_t I2C_SDA_READ_LEVEL(void)
{
    return I2C_SDA_READ();
}

static void I2C_SDA_SET_INPUT(void)
{
    I2C_SDA_1(); // 释放SDA线
}

static void I2C_SDA_SET_OUTPUT(void)
{
}

static void I2C_Delay(uint32_t us)
{
    HAL_Delay_us(us);
}
